package plp.functional1.expression;

import java.util.ArrayList;
import java.util.List;

import plp.expressions1.util.Tipo;
import plp.expressions2.expression.Expressao;
import plp.expressions2.expression.Valor;
import plp.expressions2.expression.ValorConcreto;
import plp.expressions2.memory.AmbienteCompilacao;
import plp.expressions2.memory.AmbienteExecucao;
import plp.expressions2.memory.VariavelJaDeclaradaException;
import plp.expressions2.memory.VariavelNaoDeclaradaException;
import plp.functional2.expression.MapException;

public class ValorTupla extends ValorConcreto<List<Valor>> {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	public ValorTupla(List tupla) {
		super(tupla);
	}
	
	public Valor get(int i) throws TuplaException {
		try {
			return this.valor().get(i);
		} catch (IndexOutOfBoundsException ex) {
			throw new TuplaException("estouro de limite da tupla. " 
					+ ex.getMessage());
		}
	}
	
	public Valor avaliar(AmbienteExecucao amb) throws TuplaException, 
		VariavelNaoDeclaradaException, VariavelJaDeclaradaException, MapException {
		List<Valor> listaAux = new ArrayList<Valor>();
		
		for (Expressao exp : this.valor()) {
			listaAux.add(exp.avaliar(amb));
		}
		
		setValor(listaAux);
		return this;
	}

	public boolean checaTipo(AmbienteCompilacao amb) {
		return true;
	}

	public Tipo getTipo(AmbienteCompilacao amb) throws VariavelNaoDeclaradaException, VariavelJaDeclaradaException {
		return Tipo.TIPO_TUPLA;
	}
	
	/**
	 * Retorna a aridade desta funcao.
	 * 
	 * @return a aridade desta funcao.
	 */
	public int getAridade() {
		return valor().size();
	}
	
	public String toString() {
		StringBuffer sb = new StringBuffer();
		sb.append("(");

		List<Valor> listaExp = this.valor();
         
		if (!(listaExp == null) && !listaExp.isEmpty() ) {

			if(listaExp.size() == 1){
				sb.append(listaExp.get(0).toString() + ",)");
				return sb.toString();

			}
			for (Valor exp : listaExp) {
				sb.append(exp.toString() + ",");
			}
			sb.deleteCharAt(sb.length()-1);
		}
		sb.append(")");
		return sb.toString();
	}

}
